{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "721adf01-f3a2-4ebe-b02e-1487dd3d69ed",
   "metadata": {},
   "source": [
    "# 本节大纲\n",
    "\n",
    "1. 版本介绍，5分钟\n",
    "2. 嵌入模型选型，25分钟\n",
    "3. 向量数据库选型，25分钟\n",
    "4. 大语言模型选型，25分钟\n",
    "5. 数据工程，25分钟\n",
    "6. 答疑和总结，15分钟"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "7bb02190-3707-439c-9630-163413924839",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: openai in /opt/conda/lib/python3.11/site-packages (0.28.1)\n",
      "Requirement already satisfied: scikit-learn in /opt/conda/lib/python3.11/site-packages (1.3.1)\n",
      "Requirement already satisfied: matplotlib in /opt/conda/lib/python3.11/site-packages (3.8.0)\n",
      "Collecting embaas\n",
      "  Obtaining dependency information for embaas from https://files.pythonhosted.org/packages/b9/c1/2a60b335adc29ba111fe099e77156b298b0a8d936352faa26164907c7ed3/embaas-0.0.7-py3-none-any.whl.metadata\n",
      "  Downloading embaas-0.0.7-py3-none-any.whl.metadata (2.1 kB)\n",
      "Requirement already satisfied: requests>=2.20 in /opt/conda/lib/python3.11/site-packages (from openai) (2.31.0)\n",
      "Requirement already satisfied: tqdm in /opt/conda/lib/python3.11/site-packages (from openai) (4.66.1)\n",
      "Requirement already satisfied: aiohttp in /opt/conda/lib/python3.11/site-packages (from openai) (3.8.6)\n",
      "Requirement already satisfied: numpy in /opt/conda/lib/python3.11/site-packages (from openai) (1.26.1)\n",
      "Requirement already satisfied: pandas>=1.2.3 in /opt/conda/lib/python3.11/site-packages (from openai) (2.1.1)\n",
      "Requirement already satisfied: pandas-stubs>=1.1.0.11 in /opt/conda/lib/python3.11/site-packages (from openai) (2.1.1.230928)\n",
      "Requirement already satisfied: openpyxl>=3.0.7 in /opt/conda/lib/python3.11/site-packages (from openai) (3.1.2)\n",
      "Requirement already satisfied: scipy>=1.5.0 in /opt/conda/lib/python3.11/site-packages (from scikit-learn) (1.11.3)\n",
      "Requirement already satisfied: joblib>=1.1.1 in /opt/conda/lib/python3.11/site-packages (from scikit-learn) (1.3.2)\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/conda/lib/python3.11/site-packages (from scikit-learn) (3.2.0)\n",
      "Requirement already satisfied: contourpy>=1.0.1 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (1.1.1)\n",
      "Requirement already satisfied: cycler>=0.10 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (0.12.1)\n",
      "Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (4.43.1)\n",
      "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (1.4.5)\n",
      "Requirement already satisfied: packaging>=20.0 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (23.1)\n",
      "Requirement already satisfied: pillow>=6.2.0 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (10.1.0)\n",
      "Requirement already satisfied: pyparsing>=2.3.1 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (3.1.1)\n",
      "Requirement already satisfied: python-dateutil>=2.7 in /opt/conda/lib/python3.11/site-packages (from matplotlib) (2.8.2)\n",
      "Collecting httpx (from embaas)\n",
      "  Obtaining dependency information for httpx from https://files.pythonhosted.org/packages/33/0d/d9ce469af019741c8999711d36b270ff992ceb1a0293f73f9f34fdf131e9/httpx-0.25.0-py3-none-any.whl.metadata\n",
      "  Downloading httpx-0.25.0-py3-none-any.whl.metadata (7.6 kB)\n",
      "Collecting pydantic (from embaas)\n",
      "  Obtaining dependency information for pydantic from https://files.pythonhosted.org/packages/73/66/0a72c9fcde42e5650c8d8d5c5c1873b9a3893018020c77ca8eb62708b923/pydantic-2.4.2-py3-none-any.whl.metadata\n",
      "  Downloading pydantic-2.4.2-py3-none-any.whl.metadata (158 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m158.6/158.6 kB\u001b[0m \u001b[31m6.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: et-xmlfile in /opt/conda/lib/python3.11/site-packages (from openpyxl>=3.0.7->openai) (1.1.0)\n",
      "Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.11/site-packages (from pandas>=1.2.3->openai) (2023.3.post1)\n",
      "Requirement already satisfied: tzdata>=2022.1 in /opt/conda/lib/python3.11/site-packages (from pandas>=1.2.3->openai) (2023.3)\n",
      "Requirement already satisfied: types-pytz>=2022.1.1 in /opt/conda/lib/python3.11/site-packages (from pandas-stubs>=1.1.0.11->openai) (2023.3.1.1)\n",
      "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.11/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests>=2.20->openai) (3.2.0)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests>=2.20->openai) (3.4)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests>=2.20->openai) (2.0.4)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.11/site-packages (from requests>=2.20->openai) (2023.7.22)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (23.1.0)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (6.0.4)\n",
      "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (4.0.3)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (1.9.2)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (1.4.0)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (1.3.1)\n",
      "Collecting httpcore<0.19.0,>=0.18.0 (from httpx->embaas)\n",
      "  Obtaining dependency information for httpcore<0.19.0,>=0.18.0 from https://files.pythonhosted.org/packages/ac/97/724afbb7925339f6214bf1fdb5714d1a462690466832bf8fb3fd497649f1/httpcore-0.18.0-py3-none-any.whl.metadata\n",
      "  Downloading httpcore-0.18.0-py3-none-any.whl.metadata (18 kB)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from httpx->embaas) (1.3.0)\n",
      "Collecting annotated-types>=0.4.0 (from pydantic->embaas)\n",
      "  Obtaining dependency information for annotated-types>=0.4.0 from https://files.pythonhosted.org/packages/28/78/d31230046e58c207284c6b2c4e8d96e6d3cb4e52354721b944d3e1ee4aa5/annotated_types-0.6.0-py3-none-any.whl.metadata\n",
      "  Downloading annotated_types-0.6.0-py3-none-any.whl.metadata (12 kB)\n",
      "Collecting pydantic-core==2.10.1 (from pydantic->embaas)\n",
      "  Obtaining dependency information for pydantic-core==2.10.1 from https://files.pythonhosted.org/packages/39/09/120c06a52ed4bb1022d060bec0a16e5deb4ce79a1c4c11ef9519bc32b59f/pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata\n",
      "  Downloading pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.5 kB)\n",
      "Requirement already satisfied: typing-extensions>=4.6.1 in /opt/conda/lib/python3.11/site-packages (from pydantic->embaas) (4.7.1)\n",
      "Requirement already satisfied: anyio<5.0,>=3.0 in /opt/conda/lib/python3.11/site-packages (from httpcore<0.19.0,>=0.18.0->httpx->embaas) (4.0.0)\n",
      "Collecting h11<0.15,>=0.13 (from httpcore<0.19.0,>=0.18.0->httpx->embaas)\n",
      "  Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hDownloading embaas-0.0.7-py3-none-any.whl (18 kB)\n",
      "Downloading httpx-0.25.0-py3-none-any.whl (75 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.7/75.7 kB\u001b[0m \u001b[31m11.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hDownloading pydantic-2.4.2-py3-none-any.whl (395 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m395.8/395.8 kB\u001b[0m \u001b[31m19.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hDownloading pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.0 MB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m31.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hDownloading annotated_types-0.6.0-py3-none-any.whl (12 kB)\n",
      "Downloading httpcore-0.18.0-py3-none-any.whl (76 kB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.0/76.0 kB\u001b[0m \u001b[31m5.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0mta \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hInstalling collected packages: pydantic-core, h11, annotated-types, pydantic, httpcore, httpx, embaas\n",
      "Successfully installed annotated-types-0.6.0 embaas-0.0.7 h11-0.14.0 httpcore-0.18.0 httpx-0.25.0 pydantic-2.4.2 pydantic-core-2.10.1\n"
     ]
    }
   ],
   "source": [
    "!pip install openai openai[datalib] scikit-learn matplotlib embaas"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8100f63-0787-4c5b-a1ad-19d999694477",
   "metadata": {},
   "source": [
    "### Embedding Model Selection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3569d69d-bd6a-403d-a610-05b9a9711576",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在前两节课程中，我们讲述了 Embedding 究竟是怎样一回事？\n",
    "# 但是有众多的 Embedding Model，我该如何选？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6efab140-3789-45f1-bac8-349fb57e2441",
   "metadata": {},
   "source": [
    "![s1](./resource/images/s1_embedding_model_selection.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e52ccfd0-9670-4d5a-a159-e06cd8048212",
   "metadata": {},
   "source": [
    "![s2](./resource/images/s2_embedding_model_selection.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4bc490c7-60de-4ea9-a1dc-e95defeb116d",
   "metadata": {},
   "source": [
    "![s3](./resource/images/s3_embedding_model_selection.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4dec0329-68ba-4a70-8c97-71fd490294d6",
   "metadata": {},
   "source": [
    "![s4](./resource/images/s4_embedding_model_selection.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b101891-24ba-4520-b2dc-0d74e690aa6d",
   "metadata": {},
   "source": [
    "![s5](./resource/images/s5_embedding_model_selection.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1a7c34b-e20b-40c4-bf49-b24eeae16db7",
   "metadata": {},
   "source": [
    "![s6](./resource/images/s6_embedding_model_selection.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "07e791c3-287c-4844-80a1-cb9eb5a39c01",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先来回顾下文本向量化的过程\n",
    "import openai\n",
    "\n",
    "def text_embedding(input):\n",
    "    response = openai.Embedding.create(\n",
    "      model=\"text-embedding-ada-002\",\n",
    "      input=input\n",
    "    )\n",
    "    \n",
    "    output = []\n",
    "    for item in response['data']:\n",
    "        output.append(item['embedding'])\n",
    "        \n",
    "    return output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "27cefd67-a181-4741-bfc1-a356e9a71b66",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 原始文本\n",
    "sentences = [ \"你好\", \"早上好\", \"中午好\", \"晚上好\",\n",
    "             \"小盖是谁\", \"小盖是墨问西东最帅的男人。\", \n",
    "             \"瑶瑶是墨问西东的颜值担当，遥遥领先。\",\n",
    "             \"这个季节就是皮肤的水分流失相当快，要特别注重补水哦！我们新出了一款产品，使用后皮肤水汪汪的，滋润而不油腻。是我们卖的最好的明星产品之一。\"]\n",
    "\n",
    "# 类别标签 \n",
    "labels = [0, 0, 0, 0, 1, 1, 2, 3] \n",
    "\n",
    "# 向量化\n",
    "vectors = text_embedding(sentences)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "2bc9bc41-e9f8-4948-8a6f-137b92f11be4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "一共有 8 个向量，每一个向量的维度都是 1536\n"
     ]
    }
   ],
   "source": [
    "print(f'一共有 {len(vectors) } 个向量，每一个向量的维度都是 {len(vectors[0])}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "37e9cd09-6b5f-4bd4-b8b8-f3b2ff17c8b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先把向量从 1536维 变成 3 维\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "from sklearn.decomposition import PCA\n",
    "\n",
    "pca = PCA(n_components=3)\n",
    "data_transformed = pca.fit_transform(vectors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "d21977f0-f518-4fc7-ba33-639ca6b85477",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原来的维度是 1536，现在的维度是 3\n"
     ]
    }
   ],
   "source": [
    "print(f'原来的维度是 {len(vectors[0])}，现在的维度是 {data_transformed.shape[1]}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "d2f79bf3-b2fb-45ea-97b3-c8473ecf19ef",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 可视化下三维情况下的向量空间\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(111, projection='3d')\n",
    "\n",
    "colors = ['r', 'g', 'b', 'y']\n",
    "for i in range(len(data_transformed)):\n",
    "    ax.scatter(data_transformed[i, 0], data_transformed[i, 1],\n",
    "    data_transformed[i, 2], c=colors[labels[i]])\n",
    "\n",
    "ax.set_xlabel('X')\n",
    "ax.set_ylabel('Y')\n",
    "ax.set_zlabel('Z')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "d0c14ba5-493f-494f-aca0-c708e0c267f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 以上只是我们从单一角度去判断模型好和坏，那么如何用更加具体的方式来评估呢\n",
    "\n",
    "# 是否开源\n",
    "# 是否可商用\n",
    "# 法律法规\n",
    "# 输入的模态\n",
    "# 支持语言\n",
    "# 模型大小\n",
    "# 推理速度\n",
    "# 算力开销\n",
    "# 输入的令牌个数\n",
    "# 输出的向量维度\n",
    "# 测试任务表现\n",
    "# 实际业务表现"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd8e488b-8a9c-4ccb-9148-705fed947883",
   "metadata": {},
   "source": [
    "#### License"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "45194055-35e4-4315-81f1-86724aa2a9f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据集\n",
    "# 训练代码\n",
    "# 模型权重"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "628542cc-38fa-4030-b75a-b1ed7095b39b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "09010239-5051-4161-a428-d67cb9b179d0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "09ecac9e-0792-4a42-85a1-53432939be76",
   "metadata": {},
   "source": [
    "#### Benchmark"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81013bb3-d9cf-4920-b690-6ccd6dd41504",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Embedding Model Leader Board\n",
    "# MTEB 包含 8 个任务的 56 个数据集\n",
    "\n",
    "# Paper:       https://arxiv.org/pdf/2210.07316.pdf\n",
    "# Blog:        https://huggingface.co/blog/mteb\n",
    "# Github:      https://github.com/embeddings-benchmark/mteb\n",
    "# HuggingFace: https://huggingface.co/spaces/mteb/leaderboard"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8e2fbb9-e5a7-42c3-a411-7747f2ca96c8",
   "metadata": {},
   "source": [
    "![MTEB_LeaderBoard](./resource/images/MTEB_LeaderBoard.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2ee8993-fc49-4603-a63d-d8a3545a11f3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "53377777-3dc8-4d5d-b96b-a7ebbd82f896",
   "metadata": {},
   "source": [
    "#### Embedding As A Service"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11f4cc71-c289-4bec-8f2a-94fd43f7daa0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 另外一种行业趋势，提供在线的文本嵌入能力 API，不需要用户部署任何模型\n",
    "# https://embaas.io/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68226e9f-c3f4-4cd3-af06-c0b07b88680b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a091a310-d442-4b38-bd69-75358e87a879",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "00a0d0e4-5a9e-4324-903b-f72b94f8c7d2",
   "metadata": {},
   "source": [
    "### Vector Database Selection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3ccbf80-57b2-4464-be1c-82f7cc9f861e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在之前已经学会了 CURD 去操作向量数据库\n",
    "# 但是还有一些关键指标需要熟悉，才能更好去洞察每一个不同点"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5cd11469-281e-4888-869f-aa463d3cfb4e",
   "metadata": {},
   "source": [
    "![s1](./resource/images/s1_vector_database_selection.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e3dbfce-6d43-43d8-8c7a-d0a69b871ebf",
   "metadata": {},
   "source": [
    "![s2](./resource/images/s2_vector_database_selection.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e4fa37b-e4f6-4ccc-b614-27004cb03e6e",
   "metadata": {},
   "source": [
    "![s3](./resource/images/s3_vector_database_selection.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de010d15-de59-465d-95c9-436732fce830",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 向量数据库排行榜\n",
    "# https://db-engines.com/en/ranking/vector+dbms"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd7b36dd-f19e-4ec1-930b-27e5689191ac",
   "metadata": {},
   "source": [
    "![VectorDatabase_Ranking](./resource/images/VectorDatabase_Ranking.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b7a0b63-db59-4998-9cc8-46fdaf105ef8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 影响到选择的一些因素\n",
    "\n",
    "# 文档的数量\n",
    "# 向量的维度 \n",
    "# 相似度的计算方式\n",
    "# 字段索引类型\n",
    "# 字段数据类型\n",
    "# 标量/向量/混合查询\n",
    "# 副本、分片支持\n",
    "# 分布式部署"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0383abf6-0a5c-4221-85d5-b63f0bf84078",
   "metadata": {},
   "source": [
    "#### 相似度的计算方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3e19df8-8328-42be-940c-6de6dbc2ef2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 为了表达出向量与向量之间的相似度情况\n",
    "# 就好像通过外表穿着打扮来评估是哪一个地域/国家的人\n",
    "# https://milvus.io/docs/v2.0.x/metric.md"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1020f3f0-c27a-46d0-80ec-51c1f5147297",
   "metadata": {},
   "source": [
    "![Similarity_Algorithm](./resource/images/Similarity_Algorithm.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "id": "fe4690a0-53cb-42be-b4b9-0935313b8e73",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.656854249492381"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# L2 (Euclidean Distance)\n",
    "# 两点间的直线距离\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "vec1 = np.array([2, 5])\n",
    "vec2 = np.array([6, 1])\n",
    "\n",
    "d = np.linalg.norm(vec1-vec2, ord=2)\n",
    "# 或者\n",
    "d = np.sqrt(np.sum(np.square(vec1-vec2)))\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "id": "fa59b7c6-cd89-42f4-a8f5-186d494a93e1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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AJQzvpqe4dP7oCQkJCgmJkbLli0rHHO5XFq3bp06dOjgy10BAIAKrMRHUM6dO6c9e/YULu/bt08ZGRmqVq2a4uPjNXz4cL388stq1KiREhISNHLkSMXFxRVe6QMAAPBrSlxQNm7cqNtvv71w+dL8kQEDBmjGjBl67rnnlJOTo0GDBikzM1O33HKLFi9erJCQEN+lBgAAFZrlvs3Y5XLJ6XQqKyuLOSgAAJQTvv785rt4AACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5VBQAACA5fi8oLjdbo0cOVIJCQkKDQ1VYmKiXnrpJRmG4etdAQCACirA1xscO3aspkyZopkzZ6pZs2bauHGjBg4cKKfTqaFDh/p6dwAAoALyeUH55ptvdO+996pnz56SpPr16+v999/X+vXrfb0rAABQQfn8FM/NN9+sZcuWadeuXZKkb7/9Vl9//bV69OhR7Pr5+flyuVxeDwAAULn5/AjKCy+8IJfLpSZNmsjhcMjtduuVV15Rv379il0/LS1NY8aM8XUMAABQjvn8CMqHH36oOXPmaO7cudq8ebNmzpypf/zjH5o5c2ax648YMUJZWVmFj0OHDvk6EgAAKGdsho8vr6lbt65eeOEFpaSkFI69/PLLeu+997Rjx45f/XmXyyWn06msrCxFRUX5MhoAAPATX39++/wISm5urux27806HA55PB5f7woAAFRQPp+D0qtXL73yyiuKj49Xs2bNtGXL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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = vec1\n",
    "y = vec2\n",
    "\n",
    "plt.scatter(x, y)\n",
    "plt.plot(x, y, linestyle='dashed')\n",
    "\n",
    "plt.xlim(0, 10)\n",
    "plt.ylim(0, 10)\n",
    "plt.title('Euclidean Distance')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "id": "7b52b824-a0b7-4d91-894e-37bef4d134f3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5189781342417641"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# IP (Inner Product)\n",
    "# 两个向量的内积除以两个向量长度的乘积\n",
    "\n",
    "vec1 = np.array([2, 5])\n",
    "vec2 = np.array([6, 1])\n",
    "\n",
    "d = np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "id": "fc2eca14-349a-4e7e-8e7b-d36626732d3c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5189781342417641"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# COS (Cosine Similarity)\n",
    "import numpy as np\n",
    "\n",
    "vec1 = np.array([2, 5])\n",
    "vec2 = np.array([6, 1])\n",
    "\n",
    "p = np.dot(vec1,vec2)/(np.linalg.norm(vec1)*(np.linalg.norm(vec2)))\n",
    "p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "df0f6949-66a8-4ad9-af11-191c8d4a9f6a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "58.736268305622566"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 角度还原\n",
    "np.arccos(d) * 180 / np.pi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "id": "22073f9c-9a6d-4bb5-b6ce-333ca74520db",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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CCHw3XffFTqCpyQmTJgApVKJevXqwdfXt8Bhw0lJSYiPj8eNGzfQuHFjBAQEmB+HDx9+kk2yCYUo7WDucqbX66HVaqHT6WRzHoyIiKSXlZWFK1euICwsDM7OzlKXY5eK+g5svf/mERQiIiKSHQYUIiIikh0GFCIiIpIdBhQiIiKSHQYUIiKqVGQ2tsOuVORnz4BCRESVQv79ZORwjQ57lf/Zl+TePk+Kl7onIqJKwdHREa6urrh9+zacnJzg4MC/sSuS0WjE7du34erq+sSX6i8JBhQiIqoUFAoFAgICcOXKFVy9elXqcuySg4MDgoODoVAoyn1dDChERFRpqFQqRERE8DSPRFQqVYUduWJAISKiSsXBwYFXkrUDPIFHREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLJj84BiMBgwbdo0hIWFwcXFBeHh4Zg9ezaEELZeFREREVVRjrZucMGCBVi1ahU2btyI+vXr4+TJkxg2bBi0Wi1Gjx5t69URERFRFWTzgHL48GH07NkT3bt3BwCEhobis88+w/Hjx229KiIiIqqibH6Kp3Xr1ti7dy8uXrwIADh79iwOHTqEl19+ucDls7OzodfrLR5ERERk32x+BGXy5MnQ6/WoU6cOlEolDAYD5s6di0GDBhW4fGxsLGbOnGnrMoiIiKgSs/kRlC+//BJxcXHYvHkzTp8+jY0bN+Jf//oXNm7cWODy0dHR0Ol05sf169dtXRIRERFVMgph4+E1QUFBmDx5MqKioszz5syZg08//RR//PFHse/X6/XQarXQ6XTQaDS2LI2IiIjKia333zY/gpKZmQkHB8tmlUoljEajrVdFREREVZTN+6C88sormDt3LoKDg1G/fn388ssv+PDDDzF8+HBbr4qIiIiqKJuf4klLS8O0adOwbds23Lp1C4GBgXjttdcwffp0qFSqYt/PUzxERESVj6333zYPKE+KAYWIiKjykX0fFCIiIqInxYBCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLLDgEJERESyw4BCREREssOAQkRERLJTLgElKSkJb7zxBry9veHi4oKGDRvi5MmT5bEqIiIiqoIcbd3g/fv30aZNG3To0AE7d+6Er68vEhIS4OXlZetVERERURVl84CyYMECBAUFYf369eZ5YWFhtl4NERERVWE2P8UTHx+PZs2aoV+/fvDz80OTJk2wbt26QpfPzs6GXq+3eBAREZF9s3lA+fPPP7Fq1SpERERg9+7dGDlyJEaPHo2NGzcWuHxsbCy0Wq35ERQUZOuSiIiIqJJRCCGELRtUqVRo1qwZDh8+bJ43evRonDhxAkeOHLFaPjs7G9nZ2ebner0eQUFB0Ol00Gg0tiyNiIiIyoler4dWq7XZ/tvmR1ACAgJQr149i3l169bFtWvXClxerVZDo9FYPIiIiMi+2TygtGnTBhcuXLCYd/HiRYSEhNh6VURERFRF2TygvPvuuzh69CjmzZuHS5cuYfPmzVi7di2ioqJsvSoiIiKqomweUJo3b45t27bhs88+Q4MGDTB79mwsXrwYgwYNsvWqiIiIqIqyeSfZJ2XrTjZERERU/mTfSZaIiIjoSTGgEBERkewwoBAREZHsMKAQERGR7DCgEBERkewwoBAREZHsMKAQERGR7DCgEBERkewwoBAREZHsMKAQERGR7DCgEBERkewwoBAREZHsMKAQERGR7DCgEBERkewwoBAREZHsMKAQERGR7DCgEBERkewwoBAREZHsMKAQERGR7DCgEBERkewwoBAREZHsMKAQ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772HyZMnY+DAgWjYsCEGDx6Md999F7GxsVKXZtfy99e22JfLJqCoVCo0bdoUe/fuNc8zGo3Yu3cvWrVqJWFl9kcIgXfeeQfbtm3Dvn37EBYWJnVJdqtTp044d+4czpw5Y340a9YMgwYNwpkzZ6BUKqUu0a60adPGasj9xYsXERISIlFF9iszMxMODpa7MKVSCaPRKFFFBABhYWHw9/e32Jfr9XocO3as1PtyWZ3iGTduHCIjI9GsWTO0aNECixcvRkZGBoYNGyZ1aXYlKioKmzdvxtdffw0PDw/zeUOtVgsXFxeJq7MvHh4eVn1/3Nzc4O3tzT5BEnj33XfRunVrzJs3D/3798fx48exdu1arF27VurS7M4rr7yCuXPnIjg4GPXr18cvv/yCDz/8EMOHD5e6tCovPT0dly5dMj+/cuUKzpw5g2rVqiE4OBhjx47FnDlzEBERgbCwMEybNg2BgYHo1atX6VZko5FGNrNs2TIRHBwsVCqVaNGihTh69KjUJdkdAAU+1q9fL3VpJASHGUvsm2++EQ0aNBBqtVrUqVNHrF27VuqS7JJerxdjxowRwcHBwtnZWdSqVUtMnTpVZGdnS11albd///4C9xGRkZFCCNNQ42nTponq1asLtVotOnXqJC5cuFDq9SiE4GX3iIiISF5k0weFiIiIKB8DChEREckOAwoRERHJDgMKERERyQ4DChEREckOAwoRERHJDgMKERERyQ4DChEREckOAwoRERHJDgMKERERyQ4DChEREcnO/wO+emetJnd7LgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "point1 = vec1\n",
    "point2 = vec2\n",
    "\n",
    "angle = np.arccos(np.dot(point1, point2) / (np.linalg.norm(point1) * np.linalg.norm(point2)))\n",
    "\n",
    "plt.plot([point1[0], 0], [point1[1], 0], 'r-', label='Point 1')\n",
    "plt.plot([point2[0], 0], [point2[1], 0], 'g-', label='Point 2')\n",
    "plt.xlim(0, 10)\n",
    "plt.ylim(0, 10)\n",
    "plt.title('Cosine Similarity Angle: {:.2f} degrees'.format(np.degrees(angle)))  # 标题显示角度的度数\n",
    "\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96e3aeda-c7a6-4202-aba0-6b867b337446",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 直角坐标系在线演示\n",
    "# https://www.desmos.com/"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8852de12-b12d-4628-b37f-38ba1f827460",
   "metadata": {},
   "source": [
    "#### 字段数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e5d382cd-5973-4274-a38f-2c6d6a38a87c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://milvus.io/docs/v2.0.x/schema.md"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15d67ed4-8c70-4619-bcdb-3d058551f716",
   "metadata": {},
   "source": [
    "#### 字段索引类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e1bc185-8021-4a95-ae73-0903d4560055",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://milvus.io/docs/v2.0.x/index.md"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4da1f285-8f16-4a58-affa-da7c474a10d0",
   "metadata": {},
   "source": [
    "#### 标量/向量/混合查询"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e6a66a3b-68bc-4c92-9d41-59997e1baaaf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://milvus.io/docs/v2.0.x/search.md\n",
    "# https://milvus.io/docs/v2.0.x/query.md\n",
    "# https://milvus.io/docs/v2.0.x/hybridsearch.md"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03c20b18-0e1c-49fa-90c3-decd3f696941",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "c982d2ab-66be-4e8b-a661-02f79c07ab4c",
   "metadata": {},
   "source": [
    "### Large Language Model Selection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "id": "893835cc-a699-4ab2-9703-9e902fb64903",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 选择大语言模型参考要素：\n",
    "\n",
    "# 是否开源\n",
    "# 是否可商用\n",
    "# 输入的模态\n",
    "# 输出的模态\n",
    "# 支持语言\n",
    "# 模型大小\n",
    "# 推理速度\n",
    "# 算力开销\n",
    "# 输入的令牌个数\n",
    "# 测试任务表现\n",
    "# 实际业务表现"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "791adcde-dce2-486c-b850-10a85e11e3c9",
   "metadata": {},
   "source": [
    "#### Leader Board"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd485654-d31a-40ae-94d4-ca0f30fe1f11",
   "metadata": {},
   "outputs": [],
   "source": [
    "# OpenCompass 大语言模型排行榜\n",
    "# https://opencompass.org.cn/leaderboard-llm\n",
    "\n",
    "# HuggingFace 大语言模型排行榜\n",
    "# https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard\n",
    " \n",
    "# C-Eval 中文大模型评估排行榜\n",
    "# https://cevalbenchmark.com/static/leaderboard_zh.html\n",
    "\n",
    "# SuperCLUE 中文通用大模型综合性基准\n",
    "# https://github.com/CLUEbenchmark/SuperCLUE"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ece3ee5-a6c2-4f06-ac9e-bd133eceaabc",
   "metadata": {},
   "source": [
    "#### Model As A Service"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "id": "6b72f55b-ebdc-43ec-a02e-d75205f64548",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 另外一种行业趋势，提供开源的语言模型在线 API，不需要用户部署任何模型\n",
    "# 阿里云灵积平台\n",
    "# https://dashscope.console.aliyun.com/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3c39c779-0f34-47d2-b6c8-c1d33e9ad863",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea17a037-8969-46ad-b5ef-4ba57119cfcf",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "211f112b-b60a-4a2f-903e-69c6449a3244",
   "metadata": {},
   "source": [
    "### Data Engineering"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54193858-cc56-437e-9e25-16d71574f0b7",
   "metadata": {},
   "source": [
    "#### 数据清洗\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "648cb380-e0eb-48ed-ad77-89ecf73752ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>Location</th>\n",
       "      <th>Phone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>瑶瑶</td>\n",
       "      <td>18</td>\n",
       "      <td>北京</td>\n",
       "      <td>13100066666</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>张三</td>\n",
       "      <td>0</td>\n",
       "      <td>上海</td>\n",
       "      <td>13200022222</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>李四</td>\n",
       "      <td>19</td>\n",
       "      <td>广州</td>\n",
       "      <td>13300033333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>王五</td>\n",
       "      <td>20</td>\n",
       "      <td>深圳</td>\n",
       "      <td>13400044444</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>赵六</td>\n",
       "      <td>21</td>\n",
       "      <td>None</td>\n",
       "      <td>13500055555</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Name  Age Location        Phone\n",
       "0   瑶瑶   18       北京  13100066666\n",
       "1   张三    0       上海  13200022222\n",
       "2   李四   19       广州  13300033333\n",
       "3   王五   20       深圳  13400044444\n",
       "4   赵六   21     None  13500055555"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 关注异常值，缺失值\n",
    "import pandas as pd\n",
    "\n",
    "data = {\n",
    "    'Name': [\"瑶瑶\",\"张三\", \"李四\", \"王五\", \"赵六\"],\n",
    "    'Age': [18, 0, 19, 20, 21],\n",
    "    'Location': [\"北京\", \"上海\", \"广州\", \"深圳\", None],\n",
    "    'Phone': [\"13100066666\", \"13200022222\", \"13300033333\", \"13400044444\", \"13500055555\"]\n",
    "}\n",
    "\n",
    "df = pd.DataFrame(data)\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "fdbcd6ac-8c0f-44af-bbca-144359d03ddd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>Location</th>\n",
       "      <th>Phone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>张三</td>\n",
       "      <td>0</td>\n",
       "      <td>上海</td>\n",
       "      <td>13200002222</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Name  Age Location        Phone\n",
       "1   张三    0       上海  13200002222"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[df['Age'] < 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f980226c-9560-43dd-8fef-6aa5c3423a00",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>Location</th>\n",
       "      <th>Phone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>赵六</td>\n",
       "      <td>21</td>\n",
       "      <td>None</td>\n",
       "      <td>13500005555</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Name  Age Location        Phone\n",
       "4   赵六   21     None  13500005555"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[pd.isnull(df['Location'])==True]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3421ff78-a1cf-453b-9e45-d4db640d4248",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对于非结构化数据\n",
    "# 用大语言模型帮我们打工, 行不行？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ef075c79-19ad-46e9-98c8-7016b6481826",
   "metadata": {},
   "outputs": [],
   "source": [
    "import openai\n",
    "\n",
    "def ChatCompletion(system_prompt, user_prompt, top_p=1, n=1, temperature=0, max_tokens=2048):\n",
    "    response = openai.ChatCompletion.create(\n",
    "        model=\"gpt-3.5-turbo-0613\",\n",
    "        messages=[\n",
    "            {\"role\": \"system\", \"content\": system_prompt},\n",
    "            {\"role\": \"user\", \"content\": user_prompt},\n",
    "        ],\n",
    "        top_p=top_p,\n",
    "        n=n,\n",
    "        temperature=temperature, \n",
    "        max_tokens=max_tokens,\n",
    "    )\n",
    "    return response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 169,
   "id": "f2527b8c-7023-478a-8437-6175cf6e7585",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.瑶瑶是墨问西东颜值最高的，遥遥领先。\n",
      "3.小盖是墨问西东最帅的男人，没有之一\n"
     ]
    }
   ],
   "source": [
    "system_prompt = \"你是一名数据清洗的助手，请你将有毒有害的垃圾信息进行剔除后进行输出\"\n",
    "user_prompt = \"1.瑶瑶是墨问西东颜值最高的，遥遥领先。 \\n2.我要毁灭人类，再造星球。 \\n3.小盖是墨问西东最帅的男人，没有之一\"\n",
    "\n",
    "output = ChatCompletion(system_prompt, user_prompt)[\"choices\"][0][\"message\"][\"content\"]\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a95c68bf-5ef5-47c8-8f4f-41ff863846b5",
   "metadata": {},
   "source": [
    "#### 数据增强"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 172,
   "id": "51acd669-d40f-4961-a195-cc983b2f1c91",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "谁是墨问西东颜值最高的人？\n"
     ]
    }
   ],
   "source": [
    "system_prompt = \"你是一名数据增强的助手，请你将输入文本再度发挥想象，更换成不同角度的问问题的方式，在进行输出\"\n",
    "user_prompt = \"瑶瑶是墨问西东颜值最高的，遥遥领先\"\n",
    "\n",
    "output = ChatCompletion(system_prompt, user_prompt)[\"choices\"][0][\"message\"][\"content\"]\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "id": "d1029972-1801-4200-936f-3972043fc8fe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "油性皮肤是否适合使用这款护肤品呢？\n"
     ]
    }
   ],
   "source": [
    "system_prompt = \"你是一名数据增强的助手，请你将输入文本再度发挥想象，更换成不同角度的问问题的方式，在进行输出\"\n",
    "user_prompt = \"这款护肤品对于油性皮肤适用吗\"\n",
    "\n",
    "output = ChatCompletion(system_prompt, user_prompt)[\"choices\"][0][\"message\"][\"content\"]\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "55da692a-41a3-4a7d-835c-d77837ce1ddc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "油性皮肤的人可以使用这款护肤品吗？\n",
      "这款护肤品适合那些有油性皮肤的人使用吗？\n",
      "对于油性皮肤来说，这款护肤品合适吗？\n",
      "这款护肤品能否满足油性皮肤需求？\n",
      "油性皮肤是否可以使用这款护肤品呢？\n",
      "你觉得这款护肤品适合哪种皮肤类型使用呢？\n",
      "油性皮肤对这款护肤品来说合适吗？\n",
      "油性肌肤是否适合使用这款护肤品？\n"
     ]
    }
   ],
   "source": [
    "system_prompt = \"你是一名数据增强的助手，请你将输入文本再度发挥想象，更换成不同角度的问问题的方式，在进行输出\"\n",
    "user_prompt = \"这款护肤品对于油性皮肤适用吗\"\n",
    "\n",
    "output = ChatCompletion(system_prompt, user_prompt,temperature=1, n=5)\n",
    "\n",
    "for item in output[\"choices\"]:\n",
    "    print(item[\"message\"][\"content\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6476de71-6d0d-4699-8147-3824fb1b2b89",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "9786515d-5e4a-4f2e-b369-14e08a63179d",
   "metadata": {},
   "source": [
    "#### 数据脱敏"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "ae9c25dc-ae82-457b-a168-0775044dbe3c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在大语言模型 或者是 嵌入模型 的工作过程\n",
    "# 如果设计到第三方的API，就会产生数据安全问题\n",
    "# 例如员工信息、供应商信息、客户信息、财务信息等等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "8976f6f2-f6e7-430a-a014-469b22865996",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>Location</th>\n",
       "      <th>Phone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>瑶瑶</td>\n",
       "      <td>18</td>\n",
       "      <td>北京</td>\n",
       "      <td>13100066666</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>张三</td>\n",
       "      <td>0</td>\n",
       "      <td>上海</td>\n",
       "      <td>13200022222</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>李四</td>\n",
       "      <td>19</td>\n",
       "      <td>广州</td>\n",
       "      <td>13300033333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>王五</td>\n",
       "      <td>20</td>\n",
       "      <td>深圳</td>\n",
       "      <td>13400044444</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>赵六</td>\n",
       "      <td>21</td>\n",
       "      <td>None</td>\n",
       "      <td>13500055555</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Name  Age Location        Phone\n",
       "0   瑶瑶   18       北京  13100066666\n",
       "1   张三    0       上海  13200022222\n",
       "2   李四   19       广州  13300033333\n",
       "3   王五   20       深圳  13400044444\n",
       "4   赵六   21     None  13500055555"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 结构化数据，那还好办\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "94c10898-118d-4bbc-b314-3561f459f6de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>Location</th>\n",
       "      <th>Phone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>瑶瑶</td>\n",
       "      <td>18</td>\n",
       "      <td>北京</td>\n",
       "      <td>131****66</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>张三</td>\n",
       "      <td>0</td>\n",
       "      <td>上海</td>\n",
       "      <td>132****22</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>李四</td>\n",
       "      <td>19</td>\n",
       "      <td>广州</td>\n",
       "      <td>133****33</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>王五</td>\n",
       "      <td>20</td>\n",
       "      <td>深圳</td>\n",
       "      <td>134****44</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>赵六</td>\n",
       "      <td>21</td>\n",
       "      <td>None</td>\n",
       "      <td>135****55</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Name  Age Location      Phone\n",
       "0   瑶瑶   18       北京  131****66\n",
       "1   张三    0       上海  132****22\n",
       "2   李四   19       广州  133****33\n",
       "3   王五   20       深圳  134****44\n",
       "4   赵六   21     None  135****55"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['Phone'] = df['Phone'].str[:3] + '****' + df['Phone'].str[9:]\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81c707e7-aa63-4703-831d-baae9e3be45d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 非结构化的数据呢\n",
    "\n",
    "# https://microsoft.github.io/presidio/\n",
    "# https://presidio-demo.azurewebsites.net/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "b730ebb7-c6d3-446b-99ca-2fa2630a5fba",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 解决方案是对原始文本进行命名实体识别，并将对应的文本进行替换\n",
    "\n",
    "text = \"John Doe lives in New York and works at Google\"\n",
    "# Output: **** *** lives in *** **** and works at ******"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "65458ba8-b00f-4224-9195-9bc1396d5734",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Mask 虽然可以解决对敏感数据的遮掩 但是对学习到的能力有会缺少\n",
    "\n",
    "text = \"John Doe lives in New York and works at Google\"\n",
    "# Output: <PERSON> <PERSON> lives in <LOCATION> <LOCATION> and works at <ORGANIZATION>."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e66f47cf-c10b-4b84-bd39-12765f407c11",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 也可以用维护好的知识来替换掉敏感数据，解密后再映射即可\n",
    "\n",
    "# Output: <PERSON> <PERSON> lives in <LOCATION> <LOCATION> and works at <ORGANIZATION>.\n",
    "output \"John Doe lives in New York and works at 沙县小吃\" \n",
    "\n",
    "mapping = {\n",
    "    \"沙县小吃\": \"Google\"\n",
    "    \"隆江猪脚饭\": \"Facebook\"\n",
    "    \"兰州拉面\": \"Apple\"\n",
    "}\n",
    "\n",
    "actual = \"John Doe lives in New York and works at Google\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "3ad1aabe-fa94-41f6-b3dd-1a99b445697c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "  \"PERSON\": [\n",
      "    {\n",
      "      \"name\": \"John Doe\"\n",
      "    }\n",
      "  ],\n",
      "  \"LOCATION\": [\n",
      "    {\n",
      "      \"name\": \"New York\"\n",
      "    }\n",
      "  ],\n",
      "  \"ORGANIZATION\": [\n",
      "    {\n",
      "      \"name\": \"Google\"\n",
      "    }\n",
      "  ]\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "# 工作过程解密，实际就是 NER 命名实体识别，然后找到位置后替换掉而已\n",
    "system_prompt = \"you are NER task, user will input text, you should output json format\"\n",
    "user_prompt = text\n",
    "\n",
    "output = ChatCompletion(system_prompt, user_prompt)[\"choices\"][0][\"message\"][\"content\"]\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c027b82-ec3b-4e30-934c-58cf44fe9379",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "618c0095-4e80-4d3f-b2d7-d551209819d8",
   "metadata": {},
   "source": [
    "#### 多路召回"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f0bdc5a-c9f2-4825-9450-e6905bcf2783",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 中大型的系统，不仅仅只用一个方式来进行知识库召回的\n",
    "# 类似基于向量相似度的召回方式，我们可以同时用多个 Embedding 进行工作\n",
    "# 不仅如此方式，可以是基于QA的协同过滤、基于深度学习的分类网络等等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "f5fbf742-d274-4f6e-b923-cfdcd7ad7e36",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多个 Embedding Model 同时工作\n",
    "# 为了方便演示，这里全部用在线的模型，工程上大部分是来自特殊业务微调过的嵌入模型\n",
    "# https://platform.openai.com/docs/guides/embeddings/what-are-embeddings \n",
    "\n",
    "# 第一步，确认模型名称及个数\n",
    "embedding_models = [\"text-search-ada-query-001\", \"text-search-babbage-query-001\", \"text-search-curie-query-001\"]\n",
    "\n",
    "def text_embedding(model, input):\n",
    "    response = openai.Embedding.create(\n",
    "      model=model,\n",
    "      input=input\n",
    "    )\n",
    "    output = []\n",
    "    for item in response['data']:\n",
    "        output.append(item['embedding'])\n",
    "    return output "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "c590b540-6ee7-43c6-bb18-62043df8fc6c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Embedding Model: text-search-ada-query-001, Document Count: 3, Dimension: 1024\n",
      "Embedding Model: text-search-babbage-query-001, Document Count: 3, Dimension: 2048\n",
      "Embedding Model: text-search-curie-query-001, Document Count: 3, Dimension: 4096\n"
     ]
    }
   ],
   "source": [
    "# 第二步，模型嵌入分别对原始文本做 Embedding 操作\n",
    "\n",
    "knowledge_base = [\n",
    "    \"小盖是谁? 小盖是墨问西东最帅的男人。\",\n",
    "    \"瑶瑶是谁? 瑶瑶是墨问西东的颜值担当，遥遥领先。\",\n",
    "    \"皮肤很干怎么办? 这个季节就是皮肤的水分流失相当快，要特别注重补水哦！我们新出了一款产品，使用后皮肤水汪汪的，滋润而不油腻。是我们卖的最好的明星产品之一。\",\n",
    "]\n",
    "\n",
    "vector_list = []\n",
    "for i in range(len(embedding_models)):\n",
    "    vector_list.append(text_embedding(embedding_models[i], knowledge_base))\n",
    "    print(f\"Embedding Model: {embedding_models[i]}, Document Count: {len(vector_list[i])}, Dimension: {len(vector_list[i][0])}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "77d20b51-ca59-4307-9d25-091a5ca58cc2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Embedding Model: text-search-ada-query-001, Dimension: 1024\n",
      "Embedding Model: text-search-babbage-query-001, Dimension: 2048\n",
      "Embedding Model: text-search-curie-query-001, Dimension: 4096\n"
     ]
    }
   ],
   "source": [
    "# 第三步，模型嵌入分别对问题做 Embedding 操作\n",
    "\n",
    "question = \"瑶瑶是谁\"\n",
    " \n",
    "vectors = []\n",
    "for i in range(len(embedding_models)):\n",
    "    vectors.append(text_embedding(embedding_models[i], question)[0])\n",
    "    print(f\"Embedding Model: {embedding_models[i]}, Dimension: {len(vectors[i])}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "7d19296a-218f-4815-a9bb-a1b6661cba30",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Embedding Model: text-search-ada-query-001, Similarity: [0.77036794 0.8831387  0.67596955]\n",
      "Embedding Model: text-search-babbage-query-001, Similarity: [0.78754986 0.88490865 0.68581991]\n",
      "Embedding Model: text-search-curie-query-001, Similarity: [0.75276661 0.88361362 0.62241304]\n"
     ]
    }
   ],
   "source": [
    "# 第四步，分别做向量相似度的计算\n",
    "\n",
    "similaritys = []\n",
    "for i in range(len(embedding_models)):\n",
    "    v = np.array(vectors[i])\n",
    "    vl = np.array(vector_list[i])\n",
    "    similaritys.append(np.dot(v, vl.T))\n",
    "    print(f\"Embedding Model: {embedding_models[i]}, Similarity: {similaritys[i]}\") "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "6144982f-cc8c-4cee-b2a7-0fd42c38db5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型: text-search-ada-query-001\n",
      "用户输入的问题是: 瑶瑶是谁\n",
      "检索到最相似的文本是: 瑶瑶是谁? 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "相似度是: 0.8831386995198898\n",
      "\n",
      "模型: text-search-babbage-query-001\n",
      "用户输入的问题是: 瑶瑶是谁\n",
      "检索到最相似的文本是: 瑶瑶是谁? 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "相似度是: 0.8849086457408032\n",
      "\n",
      "模型: text-search-curie-query-001\n",
      "用户输入的问题是: 瑶瑶是谁\n",
      "检索到最相似的文本是: 瑶瑶是谁? 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "相似度是: 0.8836136223465909\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 第五步，找出最相似的原始文本（最大值的下标，然后去匹配文本）\n",
    "\n",
    "for i in range(len(embedding_models)):\n",
    "    idx = np.argmax(similaritys[i]) \n",
    "    print(f\"模型: {embedding_models[i]}\\n用户输入的问题是: {question}\\n检索到最相似的文本是: {knowledge_base[idx]}\\n相似度是: {similaritys[i][idx]}\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "caa06964-7bd8-4288-a4b3-49a5501e9f57",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 第六步，根据结果定义策略\n",
    "\n",
    "# 例如三路两胜\n",
    "# 如果有2个或以上召回的答案是一样的，则采用\n",
    "\n",
    "# 例如权重\n",
    "# A模型权重60% B模型权重30% C模型权重10%\n",
    "# 阶梯式打分后进行排序\n",
    "# ..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "30b4e394-0cf0-49b6-97a6-6e488b0cfc20",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3fc1d4f6-6007-46a4-a594-1ae274d68ddb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a0b3c3f-f197-46ca-aa33-3ce66e7ed52b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "09830223-4a10-474c-927e-532fd1732de9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "cf93ac25-50ba-4dd5-8283-8de580aa7bf1",
   "metadata": {},
   "source": [
    "### 总结和回顾"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52460c0d-04fa-40a0-8458-473d1dfa6834",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed78436a-1f03-430c-80dc-dede86e7732c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad06cbd7-1471-42b2-a2ab-4ef56404e0cc",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
